home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / RSPFCMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-07  |  10.5 KB  |  425 lines

  1. #include "global.h"
  2. #include "mbuf.h"
  3. #include "timer.h"
  4. #include "iface.h"
  5. #include "cmdparse.h"
  6. #include "rspf.h"
  7.  
  8. #if !defined(_lint)
  9. static char rcsid[] OPTIONAL = "$Id: rspfcmd.c,v 1.15 1997/09/07 21:18:28 root Exp root $";
  10. #endif
  11.  
  12. #ifdef RSPF
  13.  
  14.  
  15. int Rspfownmode = -1;
  16. static int dointerface (int argc, char *argv[], void *p);
  17. static int domessage (int argc, char *argv[], void *p);
  18. static int domaxping (int argc, char *argv[], void *p);
  19. static int dorspfmode (int argc, char *argv[], void *p);
  20. static int dorrhtimer (int argc, char *argv[], void *p);
  21. static int dotimer (int argc, char *argv[], void *p);
  22. static int doroutes (int argc, char *argv[], void *p);
  23. static int dorspfstatus (int argc, char *argv[], void *p);
  24. static int dosuspect (int argc, char *argv[], void *p);
  25. int dorspf (int argc, char **argv, void *p);
  26. static struct timer rrhtimer, rspftimer;
  27.  
  28. static const char norspf[] = "RSPF is not active - define interface first.\n";
  29.  
  30. #ifdef AUTOROUTE
  31. int RspfActive = 0;
  32. extern int Ax25_autoroute;
  33. #endif
  34.  
  35.  
  36. static struct cmds Rspfcmds[] =
  37. {
  38.     { "interface",        dointerface,    0, 0, NULLCHAR},
  39.     { "message",        domessage,    0, 0, NULLCHAR},
  40.     { "maxping",        domaxping,    0, 0, NULLCHAR},
  41.     { "mode",        dorspfmode,    0, 0, NULLCHAR},
  42.     { "rrhtimer",        dorrhtimer,    0, 0, NULLCHAR},
  43.     { "routes",        doroutes,    0, 0, NULLCHAR},
  44.     { "status",        dorspfstatus,    0, 0, NULLCHAR},
  45.     { "suspecttimer",    dosuspect,    0, 0, NULLCHAR},
  46.     { "timer",        dotimer,    0, 0, NULLCHAR},
  47.     { NULLCHAR,        NULL,        0, 0, NULLCHAR}
  48. };
  49.  
  50.  
  51. int
  52. dorspf (int argc, char **argv, void *p)
  53. {
  54.     return subcmd (Rspfcmds, argc, argv, p);
  55. }
  56.  
  57.  
  58. /* The suspect timer controls how often old links expire. When a link has
  59.  * expired, we try to renew its entry by various methods.
  60.  */
  61. static int
  62. dosuspect (int argc, char *argv[], void *p OPTIONAL)
  63. {
  64.     if (Rspfifaces == NULLRIFACE) {
  65.         tputs (norspf);
  66.         return 0;
  67.     }
  68.     if (argc < 2) {
  69.         tprintf ("Suspect timer: %lu/%lu seconds\n",
  70.              read_timer (&Susptimer) / 1000,
  71.              dur_timer (&Susptimer) / 1000);
  72.         return 0;
  73.     }
  74.     Susptimer.func = rspfsuspect;    /* what to call on timeout */
  75.     Susptimer.arg = NULL;    /* dummy value */
  76.     set_timer (&Susptimer, atol (argv[1]) * 1000L);    /* set timer duration */
  77.     start_detached_timer (&Susptimer);    /* and fire it up */
  78.     return 0;
  79. }
  80.  
  81.  
  82. /* The RRH timer controls the interval between Router-To-Router Hello
  83.  * messages. These messages announce that your station is live and well
  84.  * and that you are willing to exchange RSPF routing updates.
  85.  */
  86. static int
  87. dorrhtimer (argc, argv, p)
  88. int argc;
  89. char *argv[];
  90. void *p OPTIONAL;
  91. {
  92.     if (Rspfifaces == NULLRIFACE) {
  93.         tputs (norspf);
  94.         return 0;
  95.     }
  96.     if (argc < 2) {
  97.         tprintf ("RRH timer: %lu/%lu seconds\n",
  98.              read_timer (&rrhtimer) / 1000,
  99.              dur_timer (&rrhtimer) / 1000);
  100.         return 0;
  101.     }
  102.     rrhtimer.func = rspfevent;    /* what to call on timeout */
  103.     rrhtimer.arg = (void *) &rrhtimer;
  104.     set_timer (&rrhtimer, atol (argv[1]) * 1000L);    /* set timer duration */
  105.     start_detached_timer (&rrhtimer);/* and fire it up */
  106.     return 0;
  107. }
  108.  
  109.  
  110. /* This timer controls the interval between the RSPF routing updates. */
  111. static int
  112. dotimer (argc, argv, p)
  113. int argc;
  114. char *argv[];
  115. void *p OPTIONAL;
  116. {
  117.     if (Rspfifaces == NULLRIFACE) {
  118.         tputs (norspf);
  119.         return 0;
  120.     }
  121.     if (argc < 2) {
  122.         tprintf ("RSPF update timer: %lu/%lu seconds\n",
  123.              read_timer (&rspftimer) / 1000,
  124.              dur_timer (&rspftimer) / 1000);
  125.         return 0;
  126.     }
  127.     rspftimer.func = rspfevent;    /* what to call on timeout */
  128.     rspftimer.arg = (void *) &rspftimer;
  129.     set_timer (&rspftimer, atol (argv[1]) * 1000L);    /* set timer duration */
  130.     start_detached_timer (&rspftimer);    /* and fire it up */
  131.     return 0;
  132. }
  133.  
  134.  
  135. /* Called when either the RRH timer, the Update timer or the Suspect timer
  136.  * expires.
  137.  */
  138. void
  139. rspfevent (t)
  140. void *t;
  141. {
  142. int cmd;
  143. struct mbuf *bp;
  144. struct rspfadj *adj = NULLADJ;
  145. struct timer *tp;
  146.  
  147.     tp = (struct timer *) t;
  148.     if (tp == &rrhtimer) {
  149.         cmd = RSPFE_RRH;
  150.         start_detached_timer (tp);
  151.     } else if (tp == &rspftimer) {
  152.         cmd = RSPFE_UPDATE;
  153.         start_detached_timer (tp);
  154.     } else {
  155.         for (adj = Adjs; adj != NULLADJ; adj = adj->next)
  156.             if (&adj->timer == tp)
  157.                 break;
  158.         if (adj == NULLADJ)
  159.             return;
  160.         cmd = RSPFE_CHECK;
  161.     }
  162.     bp = ambufw (1 + sizeof (int32));
  163.     *bp->data = uchar (cmd);
  164.     memcpy (bp->data + 1, &adj, sizeof (adj));
  165.     bp->cnt = bp->size;
  166.     enqueue (&Rspfinq, bp);
  167. }
  168.  
  169.  
  170. static int
  171. domessage (argc, argv, p)
  172. int argc;
  173. char *argv[];
  174. void *p OPTIONAL;
  175. {
  176.     if (argc > 2) {
  177.         tputs ("Usage: rspf message \"<your message>\"\n");
  178.         return 0;
  179.     }
  180.     if (argc < 2) {
  181.         if (Rrh_message != NULLCHAR)
  182.             tputs (Rrh_message);
  183.     } else {
  184.         if (Rrh_message != NULLCHAR) {
  185.             free (Rrh_message);
  186.             Rrh_message = NULLCHAR;    /* reset the pointer */
  187.         }
  188.         if (!strlen (argv[1]))
  189.             return 0;    /* clearing the buffer */
  190.         Rrh_message = mallocw (strlen (argv[1]) + 5);    /* allow for EOL */
  191.         strcpy (Rrh_message, argv[1]);
  192.         strcat (Rrh_message, INET_EOL);    /* add the EOL char */
  193.     }
  194.     return 0;
  195. }
  196.  
  197.  
  198. static int
  199. domaxping (argc, argv, p)
  200. int argc;
  201. char *argv[];
  202. void *p OPTIONAL;
  203. {
  204.     return setshort (&Rspfpingmax, "Max failed pings before deleting adjacency", argc, argv);
  205. }
  206.  
  207.  
  208. static int
  209. dorspfmode (argc, argv, p)
  210. int argc;
  211. char *argv[];
  212. void *p OPTIONAL;
  213. {
  214.     if (argc < 2) {
  215.         tputs ("RSPF preferred mode is ");
  216.         if (Rspfownmode == -1)
  217.             tputs ("not set.\n");
  218.         else
  219.             tprintf ("%s.\n", (Rspfownmode & CONNECT_MODE) ? "VC mode" : "Datagram mode");
  220.         return 0;
  221.     }
  222.     switch (*argv[1]) {
  223.         case 'v':
  224.         case 'c':
  225.         case 'V':
  226.         case 'C':
  227.             Rspfownmode = (int) CONNECT_MODE;
  228.             break;
  229.         case 'd':
  230.         case 'D':
  231.             Rspfownmode = (int) DATAGRAM_MODE;
  232.             break;
  233.         case 'n':
  234.         case 'N':
  235.             Rspfownmode = -1;
  236.             break;
  237.         default:
  238.             tputs ("Usage: rspf mode [vc | datagram | none]\n");
  239.             return 1;
  240.     }
  241.     return 0;
  242. }
  243.  
  244.  
  245. static int
  246. dointerface (argc, argv, p)
  247. int argc;
  248. char *argv[];
  249. void *p OPTIONAL;
  250. {
  251. struct rspfiface *riface;
  252. struct iface *iface;
  253. struct mbuf *bp;
  254. int h, q;
  255.  
  256.     if (argc < 2) {
  257.         tputs ("Iface    Quality    Horizon\n");
  258.         for (riface = Rspfifaces; riface != NULLRIFACE; riface = riface->next)
  259.             tprintf ("%-9s%-11d%-11d\n", riface->iface->name, riface->quality,
  260.                  riface->horizon);
  261.         return 0;
  262.     }
  263.     if (argc != 4) {
  264.         tputs ("Usage: rspf interface <name> <quality> <horizon>\n");
  265.         return 1;
  266.     }
  267.     if ((iface = if_lookup (argv[1])) == NULLIF) {
  268.         tputs ("No such interface.\n");
  269.         return 1;
  270.     }
  271.     if (iface->broadcast == 0) {
  272.         tprintf ("Broadcast address for interface %s not set\n", argv[1]);
  273.         return 1;
  274.     }
  275.     q = atoi (argv[2]);
  276.     if (q < 1 || q > 127) {
  277.         tputs ("Quality must be between 1 and 127\n");
  278.         return 1;
  279.     }
  280.     h = atoi (argv[3]);
  281.     if (h < 1 || h > 255) {
  282.         tputs ("Horizon must be between 1 and 255\n");
  283.         return 1;
  284.     }
  285.     riface = (struct rspfiface *) callocw (1, sizeof (struct rspfiface));
  286.  
  287.     riface->iface = iface;
  288.     riface->quality = uchar (q);
  289.     riface->horizon = uchar (h);
  290.     riface->next = Rspfifaces;
  291.     if (Rspfifaces == NULLRIFACE) {
  292. #ifdef AUTOROUTE
  293.         RspfActive = 1;    /* Make sure ARP autorouting is off ! - WG7J */
  294.         Ax25_autoroute = 0;
  295. #endif
  296.         (void) newproc ("RSPF", 2048, rspfmain, 0, NULL, NULL, 0);
  297.     }
  298.     Rspfifaces = riface;
  299.     bp = ambufw (1 + sizeof (int32));
  300.     *bp->data = RSPFE_RRH;    /* Send an RRH immediately */
  301.     memcpy (bp->data + 1, &riface, sizeof (riface));
  302.     bp->cnt = bp->size;
  303.     enqueue (&Rspfinq, bp);
  304.     return 0;
  305. }
  306.  
  307.  
  308. /* Display accumulated routing updates */
  309. static int
  310. doroutes (argc, argv, p)
  311. int argc OPTIONAL;
  312. char *argv[] OPTIONAL;
  313. void *p OPTIONAL;
  314. {
  315. struct mbuf *bp;
  316. struct rspfrouter *rr;
  317.  
  318.     if (Rspfifaces == NULLRIFACE) {
  319.         tputs (norspf);
  320.         return 0;
  321.     }
  322.     bp = makeownupdate (INADDR_ANY, 0);
  323.     if (bp == NULLBUF && Rspfrouters == NULLRROUTER) {
  324.         tputs ("No routing information is available.\n");
  325.         return 0;
  326.     }
  327.     if (bp != NULLBUF) {
  328.         tputs ("      Local routing update:\n");
  329.         rspfnodedump (NULLFILE, &bp, 0);
  330.         tputc ('\n');
  331.     }
  332.     for (rr = Rspfrouters; rr != NULLRROUTER; rr = rr->next) {
  333.         tprintf ("      Time since receipt: %s", tformat (secclock () - rr->time));
  334.         if (rr->subseq != 0)
  335.             tprintf ("  Last subseq: %u", uchar (rr->subseq));
  336.         if (rr->sent)
  337.             tputs ("  Propagated");
  338.         tputc ('\n');
  339.         if (rr->data != NULLBUF) {
  340.             (void) dup_p (&bp, rr->data, 0, len_p (rr->data));
  341.             rspfnodedump (NULLFILE, &bp, 0);
  342.             tputc ('\n');
  343.         }
  344.     }
  345.     return 0;
  346. }
  347.  
  348.  
  349. static int
  350. dorspfstatus (argc, argv, p)
  351. int argc OPTIONAL;
  352. char *argv[] OPTIONAL;
  353. void *p OPTIONAL;
  354. {
  355. struct rspfreasm *re;
  356. struct rspfadj *adj;
  357. struct mbuf *bp;
  358. union rspf rspf;
  359.  
  360.     if (Rspfifaces == NULLRIFACE) {
  361.         tputs (norspf);
  362.         return 0;
  363.     }
  364.     tprintf ("Bad checksum %u  Bad version %u  Not RSPF interface %u\n",
  365.            Rspf_stat.badcsum, Rspf_stat.badvers, Rspf_stat.norspfiface);
  366.     tprintf ("RRH in %u  RRH out %u  Update in %u  Update out %u\n",
  367.          Rspf_stat.rrhin, Rspf_stat.rrhout, Rspf_stat.updatein,
  368.          Rspf_stat.updateout);
  369.     tprintf ("Non-adjacency update %u  Old node report %u  Polls sent %u\n",
  370.         Rspf_stat.noadjupdate, Rspf_stat.oldreport, Rspf_stat.outpolls);
  371.     if (Adjs == NULLADJ)
  372.         return 0;
  373.     tputs ("Addr            Cost    Seq    Heard    Timer     TOS    State\n");
  374.     for (adj = Adjs; adj != NULLADJ; adj = adj->next) {
  375.         tprintf ("%-15s %4u  %5u   %6lu ", inet_ntoa (adj->addr),
  376.              uchar (adj->cost), adj->seq, adj->heard);
  377.         if (run_timer (&adj->timer))
  378.             tprintf ("%5lu/%-5lu",
  379.                  read_timer (&adj->timer) / 1000L, dur_timer (&adj->timer) / 1000L);
  380.         else
  381.             tprintf ("%11s", "");
  382.         tprintf ("  %3u    ", uchar (adj->tos));
  383.         switch (adj->state) {
  384.             case RSPF_TENTATIVE:
  385.                 tputs ("Tentative");
  386.                 break;
  387.             case RSPF_OK:
  388.                 tputs ("OK");
  389.                 break;
  390.             case RSPF_SUSPECT:
  391.                 tputs ("Suspect");
  392.                 break;
  393.             case RSPF_BAD:
  394.                 tputs ("Bad");
  395.                 break;
  396.             default:
  397.                 tputs ("Unknown");
  398.                 break;
  399.         }
  400.         tputc ('\n');
  401.     }
  402.     if (run_timer (&Rspfreasmt)) {
  403.         tprintf ("Reassembly timer running: %lu/%lu seconds\n",
  404.              read_timer (&Rspfreasmt) / 1000L, dur_timer (&Rspfreasmt) / 1000L);
  405.     }
  406.     if (Rspfreasmq != NULLRREASM)
  407.         tputs ("Reassembly fragments:\n");
  408.     for (re = Rspfreasmq; re != NULLRREASM; re = re->next) {
  409.         tprintf ("src %s time since last frag %s", inet_ntoa (re->addr),
  410.              tformat ((secclock () - re->time)));
  411.         if (dup_p (&bp, re->data, 0, RSPFPKTLEN) == RSPFPKTLEN &&
  412.             ntohrspf (&rspf, &bp) != -1)
  413.             tprintf (" frag count %u/%u\n", len_q (re->data),
  414.                  rspf.pkthdr.fragtot);
  415.         else {
  416.             tputc ('\n');
  417.             free_p (bp);
  418.             continue;
  419.         }
  420.     }
  421.     return 0;
  422. }
  423.  
  424. #endif /*RSPF */
  425.